<?php

namespace Ktnw\sms\controller;

use Exception;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Ktnw\sms\Services\SmsBaseService;
use Ktnw\sms\utils\Config;
use Ktnw\sms\utils\ImageCodeUtils;
use Ktnw\sms\Validators\SmsValidator;
use Ktnw\sms\utils\SmsUtils;

/**
 * 发送短信的controller
 */
class SmsController
{
    private $smsValidator;

    /**
     * 操作成功标志
     */
    private const SUCCESS = 1;

    /**
     * 操作失败标志
     */
    private const FAIL = -1;

    /**
     * 响应代码的key
     */
    private const CODE = "code";

    /**
     * 响应提示信息的key
     */
    private const MESSAGE = "message";

    /**
     * 响应代码的key
     */
    private const DATA = "data";


    public function __construct()
    {
        $this->smsValidator = resolve(SmsValidator::class);
    }

    /**
     * 发送短信接口
     * 若不符合需求,重写该方法
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     */
    public function send(Request $request): JsonResponse
    {
        $this->smsValidator->with($request->all())->passesOrFail("send");
        if (Config::getConfigValue("smsConfig.check_image_code", false) && !$this->checkImageCode($request)) {
            return $this->fail("图形验证码未通过校验");
        }

        $phone    = $request->input("phone");
        $signName = Config::getConfigValue("smsConfig.sms_sign_name");
        $msgType  = Config::getConfigValue("smsConfig.sms_template");

        // 校验是否可以发送短信
        SmsBaseService::checkSendStatus($phone, $msgType);
        $smsPrams = ['code' => SmsUtils::strRand(6)];
        $r        = SmsUtils::sendSms($phone, $smsPrams, $signName, $msgType);
        if ($r['opFlag'] == 'success') {
            // 短信日志的其他参数; 若有,请填写。
            $otherParams = [];
            $toDB        = Config::getConfigValue("smsConfig.save_sms_log", false);
            SmsBaseService::saveSmsLog($phone, $msgType, $smsPrams["code"], $toDB, $otherParams);
            return $this->success([], "短信发送成功");
        } else {
            return $this->fail(empty($r['msg']) ? '发送短信失败' : $r['msg']);
        }
    }

    /**
     * 校验短信验证码
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     */
    public function checkSmsCode(Request $request): JsonResponse
    {
        $phone   = $request->input("phone");
        $smsCode = $request->input("smsCode");
        $msgType = Config::getConfigValue("smsConfig.sms_template");
        SmsBaseService::checkSmsCode($phone, $msgType, $smsCode);
        return $this->success([], "校验通过");
    }

    /**
     * get image code
     * 获取图形验证码
     *
     * @return JsonResponse
     */
    public function getImgCode(): JsonResponse
    {
        return $this->success(app('captcha')->create('default', true));
    }

    /**
     * 操作成功响应
     * @param mixed $data
     * @param string $message 提示信息
     * @return JsonResponse
     */
    private function success($data = [], string $message = ''): JsonResponse
    {
        return $this->out([self::CODE => self::SUCCESS, self::MESSAGE => $message, self::DATA => $data]);
    }

    /**
     * 操作失败响应
     * @param string $message
     * @return JsonResponse
     */
    private function fail(string $message = ''): JsonResponse
    {
        return $this->out([self::CODE => self::FAIL, self::MESSAGE => $message]);
    }

    /**
     * 响应
     * @param $data
     * @return mixed
     */
    private function out($data): JsonResponse
    {
        return response()->json($data)
            ->header('Content-Type', 'text/json')
            ->setEncodingOptions(JSON_UNESCAPED_UNICODE);
    }

    /**
     * 校验图形验证
     * @param Request $request
     * @return bool
     */
    private function checkImageCode(Request $request): bool
    {
        $imgCode = $request->input('imgCode');
        $imgKey  = $request->input('imgKey');
        return !(empty($imgCode) || empty($imgKey)) && ImageCodeUtils::checkImgCode($imgCode, $imgKey);
    }

}